package com.karrim.server.util.array;

import com.karrim.server.util.array.abstr.AbstractArray;
import com.karrim.server.util.array.def.Array;
import com.karrim.server.util.array.def.DynamicArray;
import com.karrim.server.util.def.Indexable;
import java.util.Arrays;
import java.util.Iterator;

/**
 *
 * @author andrea.cantafio
 */
public class DynamicList<T> extends AbstractArray<T> implements DynamicArray<T>, Indexable<T, Integer> {

    public DynamicList() {
    }

    public DynamicList(Array<T> array) {
        super(array);
        current = getSize();
    }

    public DynamicList(T[] ts) {
        this.content = ts;
        size = ts.length;
    }

    @Override
    public DynamicList add(T t) {
        if (current < content.length) {
            content[current++] = t;
            size++;
        } else {
            T[] arr = (T[]) java.lang.reflect.Array.newInstance(t.getClass(), content.length * DEFAULT_EXPANSION_RATE);
            System.arraycopy(content, 0, arr, 0, content.length);
            content = arr;
             return add(t);
        }
        return this;
    }

    @Override
    public T get(Integer index) throws ArrayIndexOutOfBoundsException {
        return content[index];
    }

    @Override
    public Integer getCapacity() {
        return content.length;
    }

    @Override
    public Iterator<T> iterator() {
        return new Iterator<T>() {
            @Override
            public boolean hasNext() {
                return (index < size && content[index] != null);
            }

            @Override
            public T next() {
                return content[index++];
            }

            @Override
            public void remove() {
                content[index] = null;
                for (int i = index; i + 1 < size; i++) {
                    content[i] = content[i + 1];
                }
            }
            private int index = 0;
        };
    }

    @Override
    public T[] toArray() {
        if (size == content.length) {
            return content;
        }
        return Arrays.copyOfRange(content, 0, size);
    }
    public final int DEFAULT_EXPANSION_RATE = 2;
    public final int DEFAULT_INITIAL_CAPACITY = 1;
    private T[] content = (T[]) new Object[DEFAULT_INITIAL_CAPACITY];
    private Integer current = 0;
}
